package agent.monitors;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Timer;
import java.util.TimerTask;

public class FileMonitor {
	private static final int DEFAULT_PERIOD = 100;
	
	private static final FileMonitor	instance	= new FileMonitor();
	private Timer						timer;
	private FileMonitorTask				monitorTask;
	private OriginChangeListener			listener;
	private TorrentMonitor 				monitor;
	
	public static FileMonitor getInstance() {
		return FileMonitor.instance;
	}
	
	private FileMonitor() {
		this.timer = new Timer(true);
	}
	
	/**
	 * Inicia o monitoramento do arquivo {@code file} com intervalos de tempo padrão de {@value #DEFAULT_PERIOD}.
	 * 
	 * @param file
	 * 			Arquivo a ser monitorado.
	 * @param listener
	 * 			Evento que irá ser ser chamado no momento que houver alterações no arquivo.
	 * 
	 * @throws FileNotFoundException
	 * 			Caso o arquivo não exista.
	 */
	public void startMonitor(File file, OriginChangeListener listener) throws FileNotFoundException {
		this.startMonitor(file, DEFAULT_PERIOD, listener);
		this.fileChanged();
	}
	
	/**
	 * Inicia o monitoramento do arquivo {@code file} com intervalos de tempo {@code period}.
	 * 
	 * @param file
	 * 			Arquivo a ser monitorado.
	 * @param period
	 * 			Intervalo de tempo entre verificações
	 * @param listener
	 * 			Evento que irá ser ser chamado no momento que houver alterações no arquivo.,
	 * 
	 * @throws FileNotFoundException
	 * 			Caso o arquivo não exista.
	 */
	public void startMonitor(File file, long period, OriginChangeListener listener) throws FileNotFoundException {
		this.stopMonitor();
		this.monitor = new ValueReader("valores.txt");
		this.monitorTask = new FileMonitorTask(file);
		this.listener = listener;
		this.timer.schedule(this.monitorTask, period, period);
	}
	
	/**
	 * Para o monitoramento do arquivo.
	 */
	public void stopMonitor() {
		if (this.monitorTask != null) {
			this.monitorTask.cancel();
		}
	}
	
	protected void fileChanged(){
		this.listener.originChanged(this.monitor);
	}
	
	public TorrentMonitor getMonitor(){
		return this.monitor;
	}
	
	/**
	 * Classe de monitoração
	 */
	class FileMonitorTask extends TimerTask {
		File	monitoredFile;
		long	lastModified;
		
		public FileMonitorTask(File file) throws FileNotFoundException {
			this.lastModified = 0;
			this.monitoredFile = file;
			if (!monitoredFile.exists()) {
				throw new FileNotFoundException("Arquivo não encontrado: " + file);
			}
			this.lastModified = monitoredFile.lastModified();
		}
		
		public void run() {
			long lastModified = monitoredFile.lastModified();
			if (lastModified != this.lastModified) {
				if (lastModified == 0L){
					//Caso o arquivo seja apagado, cancela o monitoramento
					this.cancel();
				}
				else {
					//Caso tenha mudado, dispara o evento de mudança no arquivo
					this.lastModified = lastModified;
					FileMonitor.this.fileChanged();
				}
			}
		}
	}
}